package wsi.subgraph.tree;

import java.util.List;

import org.rygh.core.model.common.StringSet;
import org.rygh.core.model.tree.Branch;
import org.rygh.semantic.model.ex.PredicatePath;
import org.rygh.semantic.model.rdf.Predicate;

public class EntityBranch extends Branch<EntityObject, EntityLeaf> {

	public EntityBranch() {

	}

	public EntityBranch(Branch<EntityObject, EntityLeaf> branch) {
		super(branch);
	}

	public EntityBranch(List<EntityLeaf> slist, List<EntityLeaf> dlist) {
		assert !slist.isEmpty();
		assert !dlist.isEmpty();

		for (int i = 0; i < slist.size() - 1; i++)
			add(slist.get(i));

		for (int i = dlist.size() - 1; i >= 0; i--)
			add(dlist.get(i));

		assert nodes.size() > 1;
	}

	public StringSet getPredicateKey() {
		PredicatePath path = getPredicatePath();

		StringSet sset = new StringSet();

		for (int i = 0; i < path.size(); i++)
			sset.add(path.getPredicate(i).getValue());

		return sset;
	}

	public PredicatePath getPredicatePath() {
		PredicatePath path = new PredicatePath();
		Predicate predicate;

		EntityLeaf n, next;
		EntityObject obj = null;
		boolean inverse = false;

		for (int i = 0; i < nodes.size() - 1; i++) {
			n = nodes.get(i);
			next = nodes.get(i + 1);
			obj = null;

			if (next == n.getParent()) {
				// inverse path
				inverse = true;
				obj = n.getValue();
			} else if (n == next.getParent()) {
				inverse = false;
				obj = next.getValue();
			}

			assert obj != null;
			predicate = new Predicate(obj.getPredicate());
			predicate.setInverse(inverse ^ obj.isInverse());
			path.add(predicate);
		}

		return path;
	}

	@Override
	public String toString() {
		return toString("\n");
	}

	public String toString(String br) {
		assert nodes.size() > 1;

		StringBuilder sb = new StringBuilder();

		EntityLeaf n, next;
		EntityObject pred_obj = null;

		for (int i = 0; i < nodes.size() - 1; i++) {
			n = nodes.get(i);
			next = nodes.get(i + 1);

			/*
			 * the direction of an entity tree is always from top to down the
			 * below codes are correct...
			 */

			if (next == n.getParent()) {
				pred_obj = n.getValue();

				sb.append(String.format("%s %s %s%s", next.getValue()
						.getValue(), pred_obj.getPredicate(), pred_obj
						.getValue().getValue(), br));
			} else if (n == next.getParent()) {
				pred_obj = next.getValue();

				sb.append(String.format("%s %s %s%s", n.getValue().getValue(),
						pred_obj.getPredicate(),
						pred_obj.getValue().getValue(), br));
			} else {
				System.err.printf(
						"entity branch disconnected, node %s, next %s.", n
								.getValue().getValue(), next.getValue()
								.getValue());
			}

		}

		return sb.toString();
	}
}
